﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;


/// <summary>
/// Summary description for ClientesCtrl
/// </summary>
public class ClientesCtrl
{

    private ClientesBD bdClientes;
    private static DataTable Clientes;
    private static ClientesEnt entCliente;
    private static ContactosEnt entContacto;
    private static object Contactos = new List<Atributos_Contactos>();
    private static object lstContactosModificados = new List<int>();
    private static object lstContactosEliminados = new List<int>();
    private static int ultimoIdBd;
    private static int idDeReferencia;
    private AtributosCtrl atributos;
    

    public ClientesCtrl()
    {
        this.bdClientes = new ClientesBD();
        this.atributos = new AtributosCtrl();
    }
    //Obtiene y retorna un dataTable con la informacion de entregables

    public DataTable ActualizarGrid()
    {
        Clientes = this.bdClientes.ConsultarClientes();
        ultimoIdBd = this.bdClientes.ObtenerUltimoIDContactos();
        idDeReferencia = ultimoIdBd;
        ultimoIdBd++;
        return Clientes;
    }
    //Recibe la cedula jurdica y consulta eñ cliente con esa cedula almacenando los datos
    //en un objeto entidad y retorna ese objeto con la informacion del entregable consultado.
    //Obtiene y guarda el ultimo ID de contactos insertado 

    public ClientesEnt ConsultarCliente(int cedulaJuridica)
    {
        ultimoIdBd = this.bdClientes.ObtenerUltimoIDContactos();
        idDeReferencia = ultimoIdBd;
        ultimoIdBd++;
		((List<Atributos_Contactos>)Contactos).Clear();
        entCliente = this.bdClientes.ConsultarCliente(cedulaJuridica);
        return entCliente;
    }


    public List<ClientesEnt> ObtenerClientes () {
        return bdClientes.ObtenerClientes();
    }

    //Encapsula los datos del nuevo cliente( cedulaJuridica, nombreCliente, telefono, correo, direccion ) creando un nuevo objeto 
    //entidad de cliente y envia el objeto como parametro al metodo InsertarCliente de la controladora
    //de base de datos. Retorna true si se realizo la insercion con exito y false en caso contrario

    public bool InsertarCliente(int cedulaJuridica, string nombreCliente, int telefono, string correo, string direccion)
    {
        bool resultado;
        ClientesEnt cliente = new ClientesEnt(cedulaJuridica, nombreCliente, telefono, correo, direccion);
        entCliente = cliente;
        resultado = this.bdClientes.InsertarCliente(cliente);
        return resultado;
    }
    //Se llama al metodo eliminar de la controladora base de datos enviado como parametro
    //la cedula juridica del ultimo cliente consultado.Retorna true si se realizo la eliminacion con exito 
    //y false en caso contrario

    public bool EliminarCliente()
    {
        return this.bdClientes.EliminarCliente(entCliente.CedulaJuridica);
    }
    //Encapsula los datos recibidos por parametro junto con la cedula del ultimo cliente
    //consultado y envia el objeto creado como parametro al metodo ActuliazarCliente de 
    //controladora de base de datos. Retorna true si se realizo la modificacion con exito 
    //y false en caso contrario

    public bool ActualizarCliente(int cedJurVieja, int cedulaJuridica, string nombreCliente, int telefono, string correo, string direccion)
    {
        ClientesEnt cliente = new ClientesEnt(cedulaJuridica, nombreCliente, telefono, correo, direccion);
        entCliente = cliente;
        return this.bdClientes.ActualizarCliente(cedJurVieja, cliente);
    }
    //Retorna todos los atributos de modulo

    public AtributosCtrl SolicitarEstadoAtributos()
    {
        return this.atributos;
    }
    //Realiza la accion correspondiente al estado en el que se encuentra
    //segun el primer parametro, si es true modifica de lo contario inserta.
    //Retorna true si la operacion realizada fue exitosa y false en caso contrario

    public bool AccionesAceptar(bool modificando, int cedJurVieja, int cedulaJuridica, string nombreCliente, int telefono, string correo, string direccion)
    {
        bool resultado;

        if (modificando)
        {
            resultado = this.ActualizarCliente(cedJurVieja, cedulaJuridica, nombreCliente, telefono, correo, direccion);
        }
        else
        {
            resultado = this.InsertarCliente(cedulaJuridica, nombreCliente, telefono, correo, direccion);
        }

        if (resultado)
        {
            this.CompletarOperacionesContactos();
        }
        else
        {
            ((List<Atributos_Contactos>)Contactos).Clear(); 
        }


        return resultado;
    }


//***************************************CONTACTOS**********************************************


    //Limpia la lista de contactos.
    public void LimpiarListaContactos()
    {
        ((List<Atributos_Contactos>)Contactos).Clear();
    }

    //Actualiza el grid de contactos cargando los contactos correspondientes al cliente que se esta consultando
    //actualmente. Agrega los contactos devueltos por la base de datos y los agrega a la lista temporal de contactos,
    //la cual es devuelta a la interfaz.
    public Object ActualizarGridContactos()
    {
        ((List<Atributos_Contactos>)Contactos).Clear();
        ((List<int>)lstContactosModificados).Clear();
        ((List<int>)lstContactosEliminados).Clear();
        object CTemp = bdClientes.ConsultarContactos(entCliente.CedulaJuridica);
        int tempSize = ((List<ContactosEnt>)CTemp).Count;
        Atributos_Contactos AtrContTemp;

        for (int i = 0; i < tempSize; i++)
        {
            int id = ((List<ContactosEnt>)CTemp)[i].Id;
            string nombre = ((List<ContactosEnt>)CTemp)[i].Nombre;
            int telefono = ((List<ContactosEnt>)CTemp)[i].Telefono;
            string correo = ((List<ContactosEnt>)CTemp)[i].Correo;
            string departamento = ((List<ContactosEnt>)CTemp)[i].Departamento;
            string puesto = ((List<ContactosEnt>)CTemp)[i].Puesto;
            int cliente = ((List<ContactosEnt>)CTemp)[i].Cliente;

            AtrContTemp = new Atributos_Contactos(id, nombre, telefono, correo, departamento, puesto, cliente);
           
            ((List<Atributos_Contactos>)Contactos).Add(AtrContTemp);
        }
        
        return Contactos;
    }

    //Devuelve la lista de contactos cargados en memoria.

    public Object ActualizarGridContactosTemporal()
    {
        return Contactos;
    }


    //Realiza la consulta de un contacto en la lista temporal en memoria y lo devuelve en forma de objeto a la interfaz.
    public ContactosEnt ConsultarContacto(int Id)
    {
        int indice = 0;
        Atributos_Contactos temporal;

        while ((((List<Atributos_Contactos>)Contactos)[indice]).Id != Id ) 
        {
            indice++;
        }

        temporal = ((List<Atributos_Contactos>)Contactos)[indice];

        entContacto = new ContactosEnt(temporal.Id, temporal.Nombre, temporal.Telefono, temporal.Correo, temporal.Departamento, temporal.Puesto, temporal.Cliente);
        
        return entContacto;
    }


    //Inserta un contacto en la lista temporal de contactos que se encuentra en memoria, asignandole un ID simulado al contacto.
    //Devuelve la verificacion de la accion.
    public bool InsertarContacto(string nombreContacto, int telefono, string correo, string departamento, string puesto, int cedJurCliente)
    {
        bool verificar;
        Atributos_Contactos temporal;

        temporal = new Atributos_Contactos(ultimoIdBd, nombreContacto, telefono, correo, departamento, puesto, cedJurCliente);

        ((List<Atributos_Contactos>)Contactos).Add(temporal);

        verificar = ((List<Atributos_Contactos>)Contactos).Contains(temporal);

        if (verificar)
        {
            ultimoIdBd++;
        }

        return verificar;
    }


    //Elimina el contacto seleccionado de la lista temporal de contactos y devuelve la verificacion de la accion. Ademas agrega
    //el ID del contacto a la lista de eliminacion mientras corresponda a un ID menor o igual al ultimo contenido en la base de 
    //datos.
    public bool EliminarContacto()
    {
        bool verificar;

        Atributos_Contactos temporal = new Atributos_Contactos(entContacto.Id, entContacto.Nombre, entContacto.Telefono, entContacto.Correo, entContacto.Departamento, entContacto.Puesto, entContacto.Cliente);

        verificar = ((List<Atributos_Contactos>)Contactos).Remove(temporal);

        if (temporal.Id <= idDeReferencia)
        {
            ((List<int>)lstContactosEliminados).Add(temporal.Id);
        }

        return verificar;
    }

    //Actualiza la informacion del contacto actual en la lista temporal de contactos y devuelve la verificacion de la operacion.

    public bool ActualizarContacto(string nombreContacto, int telefono, string correo, string departamento, string puesto, int cedJurCliente)
    {
        bool verificar;

        Atributos_Contactos entTemporal = new Atributos_Contactos(entContacto.Id, nombreContacto, telefono, correo, departamento, puesto, entContacto.Cliente);

        int index = ((List<Atributos_Contactos>)Contactos).FindIndex(delegate(Atributos_Contactos c) { return c.Id == entContacto.Id; });

        ((List<Atributos_Contactos>)Contactos)[index] = entTemporal;

        verificar = ((List<Atributos_Contactos>)Contactos).Contains(entTemporal);

        if (entTemporal.Id <= idDeReferencia)
        {
            ((List<int>)lstContactosModificados).Add(entTemporal.Id);
        }

        if (verificar)
        {
            entContacto = new ContactosEnt(entTemporal.Id, entTemporal.Nombre, entTemporal.Telefono, entTemporal.Correo, entTemporal.Departamento, entTemporal.Puesto, entTemporal.Cliente);
        }

        return verificar;
    }

    //Refleja los cambios realizados sobre la lista temporal de contactos en la base de datos siguiendo el siguiente razonamiento:
    //si el ID del contacto es menor o igual que el ultimo ID de la base de datos, se trata de una modificacion, si es mayor se trata
    //de una insercion. Finalmente elimina de la base de datos los datos marcados para eliminacion en la lista de contactos a eliminar.

    public bool CompletarOperacionesContactos()
    {
        bool resultado = true;
        bool resultadoOficial = true;
        int totalContactosCliente = ((List<Atributos_Contactos>)Contactos).Count;
        int totalEliminados = ((List<int>)lstContactosEliminados).Count;
        Atributos_Contactos contactoTemp;
        ContactosEnt contactoOperando;
        int idTemporal;

        for (int i = 0; i < totalContactosCliente; i++) 
        {
            contactoTemp = ((List<Atributos_Contactos>)Contactos)[i];

            contactoOperando = new ContactosEnt(contactoTemp.Id, contactoTemp.Nombre, contactoTemp.Telefono, contactoTemp.Correo, contactoTemp.Departamento, contactoTemp.Puesto, contactoTemp.Cliente);

            if (contactoOperando.Id <= idDeReferencia)
            {
                if (((List<int>)lstContactosModificados).Contains(contactoOperando.Id))
                {
                    resultado = this.bdClientes.ActualizarContacto(contactoOperando);
                }

            }
            else {
                resultado = this.bdClientes.InsertarContacto(entCliente, contactoOperando);
            }

            if (!resultado)
            {
                resultadoOficial = resultado;
            }            
        }


        for (int i = 0; i < totalEliminados; i++)
        {
            idTemporal = ((List<int>)lstContactosEliminados)[i];

            resultado = this.bdClientes.EliminarContacto(idTemporal);

            if (!resultado)
            {
                resultadoOficial = resultado;
            }            
        }

        return resultadoOficial;
    }

    //Realiza las acciones correspondientes a la accion de presionar el aceptar de contactos enviado por la interfaz. Procede
    //a realizar una actualizacion o una insercion de un contacto y devuelve la verificacion de la operacion realizada.
    public bool AccionesAceptarContactos(bool modificando, string nombreContacto, int telefono, string correo, string departamento, string puesto, int cedJurCliente)
    {
        bool resultado;

        if (modificando)
        {
            resultado = this.ActualizarContacto(nombreContacto, telefono, correo, departamento, puesto, cedJurCliente);
        }
        else
        {
            resultado = this.InsertarContacto(nombreContacto, telefono, correo, departamento, puesto, cedJurCliente);
        }

        return resultado;
    }

}

//################################################################################################################################
//Clase Lista_Atributos_Contactos necesaria por razones tecnológicas para evitar la violación de capas

public class Atributos_Contactos
{

    int id;

    string nombre;

    int telefono;

    string correo;

    string departamento;

    string puesto;

    int cliente;


    public static bool operator ==(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id == contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }
    }

    public static bool operator <(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id < contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }
    }

    public static bool operator >(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id > contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }
    }


    public static bool operator <=(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id <= contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }
    }

    public static bool operator >=(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id >= contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }
    }

    public static bool operator !=(Atributos_Contactos contacto1, Atributos_Contactos contacto2)
    {

        if (contacto1.Id != contacto2.Id)
        {
            return true;
        }

        else
        {
            return false;
        }

    }


    public override bool Equals(object obj)
    {

        if (!(obj is Atributos_Contactos)) return false;

        return this == (Atributos_Contactos)obj;

    }

    public int Id
    {
        get
        {
            return this.id;
        }
        set
        {
            this.id = value;
        }
    }

    public string Nombre
    {
        get
        {
            return this.nombre;
        }
        set
        {
            this.nombre = value;
        }
    }

    public int Telefono
    {
        get
        {
            return this.telefono;
        }
        set
        {
            this.telefono = value;
        }
    }

    public string Correo
    {
        get
        {
            return this.correo;
        }
        set
        {
            this.correo = value;
        }
    }

    public string Departamento
    {
        get
        {
            return this.departamento;
        }
        set
        {
            this.departamento = value;
        }
    }

    public string Puesto
    {
        get
        {
            return this.puesto;
        }
        set
        {
            this.puesto = value;
        }
    }

    public int Cliente
    {
        get
        {
            return this.cliente;
        }
        set
        {
            this.cliente = value;
        }
    }

    public Atributos_Contactos(int id, string nombre, int telefono, string correo, string departamento, string puesto, int cliente)
    {
        this.id = id;
        this.Nombre = nombre;
        this.Telefono = telefono;
        this.Correo = correo;
        this.Departamento = departamento;
        this.Puesto = puesto;
        this.Cliente = cliente;
    }

    public Atributos_Contactos(string nombre, int telefono, string correo, string departamento, string puesto, int cliente)
    {
        this.Nombre = nombre;
        this.Telefono = telefono;
        this.Correo = correo;
        this.Departamento = departamento;
        this.Puesto = puesto;
        this.Cliente = cliente;
    }

    public Atributos_Contactos(int id, string nombre)
    {
        this.id = id;
        this.Nombre = nombre;
    }
}